package com.fjwt.gz.db.typehandler;

import com.fjwt.gz.service.impl.SysConfigService;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

/**
*
* 敏感数据， 自动加解密
* 注意： 使用LambdaUpdateWrapper不支持自定义BaseTypeHandler (https://github.com/baomidou/mybatis-plus/issues/3317)
* 支持： 分页查询、 条件查询、 ID查询、 ID更新、 record+ query条件更新、 不支持LambdaUpdateWrapper ！ 切记
*
* 使用方式：
*  1. Model中       @TableName(value = "t_xxxx", autoResultMap = true)
*                 字段： @TableField(typeHandler = EncryptTypeHandler.class)
*  2. mapper.xml   字段： 加入： typeHandler="com.fjwt.gz.db.typehandler.EncryptTypeHandler"  属性。
*
* @author wg
* @site https://pt.jdyd.xyz/
* @date 2022/5/16 9:13
*/
public class EncryptTypeHandler<T> extends BaseTypeHandler<T> {

    /** 执行之前，将Java类型转换为对应的jdbc类型，用于赋值sql中参数 */
    @Override
    public void setNonNullParameter(PreparedStatement ps, int i, T parameter, JdbcType jdbcType) throws SQLException {

        // 加密存储 base64格式 空串也加密
        ps.setString(i, (parameter == null ? null : SysConfigService.DB_ENCRYPT_SM4.encryptBase64(parameter.toString() ) ));
    }

    /** 根据列名从resultSet中获取，将JDBC类型转换为Java类型 */
    @Override
    public T getNullableResult(ResultSet rs, String columnName) throws SQLException {
        return commonGetVal(rs.getString(columnName));
    }

    /** 据下标从resultSet中获取，将JDBC类型转换为Java类型*/
    @Override
    public T getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
        return commonGetVal(rs.getString(columnIndex));
    }

    /** 用于在执行完存储过程后，将JDBC类型转换为Java类型 */
    @Override
    public T getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
        return commonGetVal(cs.getString(columnIndex));
    }


    /** 通用获取值的函数 **/
    private T commonGetVal(String val){
        if(val == null){
            return null;
        }

        // 解密： 空串也解密
        return (T) SysConfigService.DB_ENCRYPT_SM4.decryptStr(val);
    }
}
